/*
 * Copyright 2017-2018 the original author(https://github.com/wj596)
 * 
 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * </p>
 */
package com.ld.security.common.shiro.realm;

import com.ld.security.common.shiro.config.CacheProperties;
import com.ld.security.common.shiro.config.ShiroProperties;
import com.ld.security.common.shiro.model.AccountModel;
import com.ld.security.common.shiro.model.PermissionModel;
import com.ld.security.common.shiro.model.RoleModel;
import com.ld.security.common.shiro.service.BaseAuthService;
import com.ld.security.common.shiro.service.PasswordAuthService;
import com.ld.security.common.shiro.token.HmacToken;
import com.ld.security.common.shiro.vo.UserInfo;
import lombok.Data;
import org.apache.shiro.authc.*;
import org.apache.shiro.authc.credential.CredentialsMatcher;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.cache.Cache;
import org.apache.shiro.cache.CacheManager;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;

@Data
public abstract class BaseAuthRealm extends AuthorizingRealm{

	@Autowired(required = false)
	BaseAuthService baseAuthService;


	ShiroProperties shiroProperties;


	CacheManager cacheManager;



	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
		String username = (String) principals.getPrimaryPrincipal();
		CacheProperties cacheProperties =  shiroProperties.getCache();
		UserInfo userInfo=null;
		if(cacheProperties.isPermissionCache()){
			Cache cache =  cacheManager.getCache(cacheProperties.getAuthCacheName());
			userInfo = (UserInfo)cache.get(username);
			if(userInfo == null){
				userInfo =  baseAuthService.getUserInfo(username);
				cache.put(username,userInfo);
			}
		}else{
			userInfo =  baseAuthService.getUserInfo(username);
		}

		SimpleAuthorizationInfo info=new SimpleAuthorizationInfo();
		for (RoleModel roleModel : userInfo.getRoles()) {
			info.addRole(roleModel.getCode());
		}
		for (PermissionModel permissionModel : userInfo.getPermissions()) {
			info.addStringPermission(permissionModel.getUrl());
		}
		return info;
	}

	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
		String username = (String)token.getPrincipal();
		AccountModel accountModel= null;
		CacheProperties cacheProperties =  shiroProperties.getCache();

		if(cacheProperties.isAuthCache()){
			Cache cache =  cacheManager.getCache(cacheProperties.getAuthCacheName());
			accountModel = (AccountModel)cache.get(username);
			if(accountModel == null){
				accountModel =  baseAuthService.findByUsername(username);
				cache.put(username,accountModel);
			}
		}else{
			accountModel =  baseAuthService.findByUsername(username);
		}

		return new SimpleAuthenticationInfo(accountModel.getUsername(),accountModel.getPassword(),this.getName());

	}

	protected abstract String getUsername(AuthenticationToken authenticationToken);



	protected abstract String getUsername(PrincipalCollection principalCollection);



	@Override
	public void setCredentialsMatcher(CredentialsMatcher credentialsMatcher) {
		super.setCredentialsMatcher(credentialsMatcher);
	}
}